package com.bys.controller;

import com.bys.entity.OrderPay;
import com.bys.util.Result;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class PayController {
    @Value("${server.port}")
    private String serverPort;
    @Resource
    private DiscoveryClient discoveryClient;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @HystrixCommand(fallbackMethod = "error_fusing", commandProperties = {
            @HystrixProperty(name = "circuitBreaker.enabled",value = "true"), //开启断路器
            @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold",value = "10"),  //请求次数超过了峰值，熔断器将会从关闭
            @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds",value = "10000"), //时间范围
            @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60") //失败率达到多少跳闸
            }
    )
    @GetMapping("/pay/hystrix/fusing")
    public String pay_fusing() throws InterruptedException {
        TimeUnit.MILLISECONDS.sleep(500);
        log.info(Thread.currentThread().getName()+ "****\n" + UUID.randomUUID().toString().replaceAll("-",""));
        return Thread.currentThread().getName()+ "****\n" + UUID.randomUUID().toString().replaceAll("-","");

    }

    @HystrixCommand(fallbackMethod = "error",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value= "2000")
    })
    @GetMapping("/pay/hystrix/ok/{payId}")
    public String pay_Ok(@PathVariable Integer payId){
        int a = 10 / 0;
        String threadName = Thread.currentThread().getName();
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        System.out.println(id+ "==ok=="+ serverPort+ threadName);
        return id+ "==ok=="+ serverPort+ threadName;
    }

    /**
     * execution.isolation.thread.timeoutInMilliseconds 表示 降级的时间
     * 如果没有再指定的时间返回，则需要降级，默认是 1000毫秒
     */
    @GetMapping("/pay/hystrix/timeout/{payId}")
    @HystrixCommand(fallbackMethod = "error",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value= "2000"),
    })
    public String pay_timeout(@PathVariable Integer payId) throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        String threadName = Thread.currentThread().getName();
        String id = UUID.randomUUID().toString().replaceAll("-", "");
        System.out.println(id+ "==ok=="+ serverPort+ threadName);
        return id +"==timeout=="+ serverPort + threadName;
    }
    @GetMapping("/provider/timeout")
    public String timeoutTest() throws InterruptedException {
        TimeUnit.SECONDS.sleep(3);
        return "提供的端口 为" + serverPort;
    }
    @GetMapping("/pay/string/getId/{payId}")
    public String getStringGetId(@PathVariable Integer payId){
        Object data = stringRedisTemplate.boundValueOps(payId.toString()).get();
        return String.valueOf(data) + "端口为： "+ serverPort;
    }
    @GetMapping("/pay/getId/{payId}")
    public Result getOrderPayById(@PathVariable Integer payId) throws JsonProcessingException {
        Object data = stringRedisTemplate.boundValueOps(payId.toString()).get();
        OrderPay orderPay = new ObjectMapper().readValue(String.valueOf(data), OrderPay.class);
        System.out.println(orderPay);
        return Result.success(orderPay);
    }
    @PostMapping("/pay/create")
    public Result createOrderPay(@RequestBody OrderPay orderPay) throws JsonProcessingException {
        stringRedisTemplate.boundValueOps(orderPay.getPayId().toString()).set(new ObjectMapper().writeValueAsString(orderPay));
        return Result.success();
    }
    public String error(Integer payId){
        return "调用异常 \t"+ Thread.currentThread().getName()+ "o(╥﹏╥)o *** "+ payId;
    }
    public String error_fusing(){
        return "系统繁忙，请稍后继续！！"+Thread.currentThread().getName();
    }

}
